package demo.word2pdf;

import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.BestMatchingMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * word转PDF
 *
 * @author zhangxinbetter@qq.com
 * @since 2024/3/19 17:07
 */
public class Main {

    public static void main(String[] args) throws Exception {
        useJsoupAndDocx4j();
    }

    /**
     * 思路：Word -> XML -> Word -> PDF
     * <p>
     * 参考：https://juejin.cn/post/6844903828861501454
     *
     * @throws Exception
     */
    private static void useJsoupAndDocx4j() throws Exception {
        // 创建一个Configuration对象
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
        // 设置config的默认字符集。一般是utf-8
        configuration.setDefaultEncoding("utf-8");
        // 参考 freemarker.cache.ByteArrayTemplateLoader 可以自定义模板加载器，从对象存储加载模板
        // https://stackoverflow.com/a/34821630
        configuration.setLocalizedLookup(false);

        configuration.setTemplateLoader(new FileTemplateLoader(new File("/Users/devin/Desktop")));
        // 从config对象中获得模板对象。需要制定一个模板文件的名字。
        Template template = configuration.getTemplate("test.xml");
        // 创建模板需要的数据集。可以是一个map对象也可以是一个pojo，把模板需要的数据都放入数据集。
        Map<String, String> root = new HashMap<>();
        root.put("hello", "hello freemarker");
        // 创建一个Writer对象，指定生成的文件保存的路径及文件名。
        // Writer out = new FileWriter(new File("/Users/devin/Desktop/test.xml"));
        StringWriter stringWriter = new StringWriter();
        BufferedWriter writer = new BufferedWriter(stringWriter);
        // 调用模板对象的process方法生成静态文件。需要两个参数数据集和writer对象。
        template.process(root, writer);
        String xmlStr = stringWriter.toString();
        // 关闭writer对象。
        writer.flush();
        writer.close();

        ByteArrayInputStream in = new ByteArrayInputStream(xmlStr.getBytes());
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in);
        String outputfilepath = "/Users/devin/Desktop/abc.pdf";
        FileOutputStream os = new FileOutputStream(new File(outputfilepath));
        // https://github.com/plutext/docx4j-export-FO/blob/master/src/samples/docx4j/org/docx4j/samples/ConvertOutPDFviaXSLFO.java
        Mapper fontMapper = new BestMatchingMapper();
        wordMLPackage.setFontMapper(fontMapper);

        FOSettings foSettings = Docx4J.createFOSettings();
        foSettings.setOpcPackage(wordMLPackage);
        foSettings.setApacheFopMime("application/pdf");

        // https://stackoverflow.com/questions/39985050/docx4j-topdf-hf-fo-file
        foSettings.setFoDumpFile(Files.createFile(
                FileSystems.getDefault().getPath("learn-java-lib/target/" + UUID.randomUUID() + ".fo")).toFile());

        // Docx4J.toPDF(wordMLPackage, os);
        Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

    }

}